package com.ctim.dao.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.boot.autoconfigure.MybatisProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;

@Configuration
@PropertySource("classpath:db.properties")
@EnableTransactionManagement(proxyTargetClass=true)// 必须基于类的代理类，否则包含@transactional的dubbo @service无法发布服务
@AutoConfigureAfter({ DataBaseConfiguration.class })
public class MybatisConfiguration {
	
	private static final Logger logger = LoggerFactory.getLogger(MybatisConfiguration.class);

	/*public MybatisConfiguration(MybatisProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider, ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
		super(properties, interceptorsProvider, resourceLoader, databaseIdProvider, configurationCustomizersProvider);
		this.properties = properties;
	}*/


	@Bean(name="sqlSession")
	@Primary
	public SqlSessionTemplate readSqlSessionFactoryBean(@Qualifier("readDataSource") DataSource readDataSource,MybatisProperties properties) throws Exception {
    	long startTime = System.currentTimeMillis();
    	SqlSessionTemplate readSqlSession = null;
    	try {
			SqlSessionFactory sessionFactory = concructFactory(readDataSource,properties);
			readSqlSession = new SqlSessionTemplate(sessionFactory);
    	} catch(Exception ex){
    		logger.error("......configruing read sqlsession is error......", ex);
    	}
        logger.info("......configruing read sqlsession end time is:{}ms......", (System.currentTimeMillis()-startTime));
        return readSqlSession;
    }

    @Bean(name="writeSqlSession")
    public SqlSessionTemplate writeSqlSessionFactoryBean(@Qualifier("writeDataSource") DataSource writeDataSource,MybatisProperties properties) throws Exception {
    	long startTime = System.currentTimeMillis();
    	SqlSessionTemplate writeSqlSession = null;
    	try {
			SqlSessionFactory sessionFactory = concructFactory(writeDataSource,properties);
			writeSqlSession = new SqlSessionTemplate(sessionFactory);
    	} catch (Exception ex){
    		logger.error("......configruing write sqlsession is error......", ex);
    	}
        logger.info("......configruing write sqlsession end time is:{}ms......", (System.currentTimeMillis()-startTime));
        return writeSqlSession;
    }

	@Bean(name="transactionManager")
	public DataSourceTransactionManager transactionManager(@Qualifier("writeDataSource") DataSource writeDataSource) {
		return new DataSourceTransactionManager(writeDataSource);
	}

	private SqlSessionFactory concructFactory(DataSource dataSource,MybatisProperties properties) {
		try {
			final SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
			factoryBean.setDataSource(dataSource);
			if (properties.getConfigurationProperties() != null) {
				factoryBean.setConfigurationProperties(properties.getConfigurationProperties());
			}
			if (StringUtils.hasLength(properties.getTypeAliasesPackage())) {
				factoryBean.setTypeAliasesPackage(properties.getTypeAliasesPackage());
			}
			if (!ObjectUtils.isEmpty(properties.resolveMapperLocations())) {
				factoryBean.setMapperLocations(properties.resolveMapperLocations());
			}
			return factoryBean.getObject();
		} catch(Exception ex){
			logger.error("......configruing sqlsession is error......", ex);
		}
		return null;
	}

}